package com.controller;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Map;
import java.util.Set;

import static org.junit.jupiter.api.Assertions.*;

/**
 * WebSocketTestController单元测试
 * 注意：由于ChatWebSocket使用静态方法，这里主要测试控制器逻辑和响应格式
 */
@ExtendWith(MockitoExtension.class)
public class WebSocketTestControllerTest {

    private WebSocketTestController controller;

    @BeforeEach
    void setUp() {
        controller = new WebSocketTestController();
    }

    @Test
    void testGetOnlineCount() {
        // 执行测试
        Map<String, Object> result = controller.getOnlineCount();

        // 验证结果结构
        assertNotNull(result);
        assertEquals(200, result.get("code"));
        assertEquals("获取成功", result.get("message"));
        assertNotNull(result.get("data"));
        
        // 验证data是数字类型
        Object data = result.get("data");
        assertTrue(data instanceof Integer || data instanceof Long, "data应该是数字类型");
    }

    @Test
    void testGetOnlineUsers() {
        // 执行测试
        Map<String, Object> result = controller.getOnlineUsers();

        // 验证结果结构
        assertNotNull(result);
        assertEquals(200, result.get("code"));
        assertEquals("获取成功", result.get("message"));
        assertNotNull(result.get("data"));
        
        // 验证data是Set类型
        Object data = result.get("data");
        assertTrue(data instanceof Set, "data应该是Set类型");
    }

    @Test
    void testSendMessage_WithValidParameters() {
        // 执行测试
        Map<String, Object> result = controller.sendMessage("user1", "Hello");

        // 验证结果结构
        assertNotNull(result);
        assertTrue(result.containsKey("code"));
        assertTrue(result.containsKey("message"));
        
        // 验证返回码是200或500（取决于用户是否在线）
        Integer code = (Integer) result.get("code");
        assertTrue(code == 200 || code == 500, "返回码应该是200或500");
        
        // 验证消息内容
        String message = (String) result.get("message");
        assertTrue(message.contains("成功") || message.contains("失败"), "消息应该包含成功或失败信息");
    }

    @Test
    void testSendMessage_WithNullUserId() {
        // 执行测试
        Map<String, Object> result = controller.sendMessage(null, "Hello");

        // 验证结果结构
        assertNotNull(result);
        assertEquals(500, result.get("code"));
        assertEquals("消息发送失败，用户可能不在线", result.get("message"));
    }

    @Test
    void testSendMessage_WithEmptyUserId() {
        // 执行测试
        Map<String, Object> result = controller.sendMessage("", "Hello");

        // 验证结果结构
        assertNotNull(result);
        assertEquals(500, result.get("code"));
        assertEquals("消息发送失败，用户可能不在线", result.get("message"));
    }

    @Test
    void testSendMessage_WithNullMessage() {
        // 执行测试
        Map<String, Object> result = controller.sendMessage("user1", null);

        // 验证结果结构
        assertNotNull(result);
        assertEquals(500, result.get("code"));
        assertEquals("消息发送失败，用户可能不在线", result.get("message"));
    }

    @Test
    void testSendMessage_WithEmptyMessage() {
        // 执行测试
        Map<String, Object> result = controller.sendMessage("user1", "");

        // 验证结果结构
        assertNotNull(result);
        assertTrue(result.containsKey("code"));
        assertTrue(result.containsKey("message"));
        
        // 验证返回码是200或500（取决于用户是否在线）
        Integer code = (Integer) result.get("code");
        assertTrue(code == 200 || code == 500, "返回码应该是200或500");
    }

    @Test
    void testGetWebSocketInfo() {
        // 执行测试
        Map<String, Object> result = controller.getWebSocketInfo();

        // 验证结果结构
        assertNotNull(result);
        assertEquals(200, result.get("code"));
        assertEquals("获取成功", result.get("message"));
        assertNotNull(result.get("data"));

        // 验证data是Map类型
        Object data = result.get("data");
        assertTrue(data instanceof Map, "data应该是Map类型");
        
        @SuppressWarnings("unchecked")
        Map<String, Object> dataMap = (Map<String, Object>) data;
        
        // 验证data包含必要的字段
        assertTrue(dataMap.containsKey("endpoint"), "data应该包含endpoint字段");
        assertTrue(dataMap.containsKey("onlineCount"), "data应该包含onlineCount字段");
        assertTrue(dataMap.containsKey("onlineUsers"), "data应该包含onlineUsers字段");
        
        // 验证字段类型
        assertEquals("/ws/chat/{userId}", dataMap.get("endpoint"));
        assertTrue(dataMap.get("onlineCount") instanceof Integer || dataMap.get("onlineCount") instanceof Long);
        assertTrue(dataMap.get("onlineUsers") instanceof Set);
    }

    @Test
    void testSendMessage_WithSpecialCharacters() {
        // 测试包含特殊字符的消息
        String specialMessage = "消息包含特殊字符：@#$%^&*()_+{}|:<>?[]\\;'\",./";
        
        // 执行测试
        Map<String, Object> result = controller.sendMessage("user1", specialMessage);

        // 验证结果结构
        assertNotNull(result);
        assertTrue(result.containsKey("code"));
        assertTrue(result.containsKey("message"));
        
        // 验证返回码是200或500（取决于用户是否在线）
        Integer code = (Integer) result.get("code");
        assertTrue(code == 200 || code == 500, "返回码应该是200或500");
    }

    @Test
    void testSendMessage_WithUnicodeCharacters() {
        // 测试Unicode字符消息
        String unicodeMessage = "Unicode消息：你好世界！🌍🚀💻";
        
        // 执行测试
        Map<String, Object> result = controller.sendMessage("user1", unicodeMessage);

        // 验证结果结构
        assertNotNull(result);
        assertTrue(result.containsKey("code"));
        assertTrue(result.containsKey("message"));
        
        // 验证返回码是200或500（取决于用户是否在线）
        Integer code = (Integer) result.get("code");
        assertTrue(code == 200 || code == 500, "返回码应该是200或500");
    }

    @Test
    void testSendMessage_WithLongMessage() {
        // 测试长消息
        StringBuilder longMessage = new StringBuilder();
        for (int i = 0; i < 1000; i++) {
            longMessage.append("这是一条很长的消息内容。");
        }
        
        // 执行测试
        Map<String, Object> result = controller.sendMessage("user1", longMessage.toString());

        // 验证结果结构
        assertNotNull(result);
        assertTrue(result.containsKey("code"));
        assertTrue(result.containsKey("message"));
        
        // 验证返回码是200或500（取决于用户是否在线）
        Integer code = (Integer) result.get("code");
        assertTrue(code == 200 || code == 500, "返回码应该是200或500");
    }

    @Test
    void testSendMessage_WithVeryLongUserId() {
        // 测试超长用户ID
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 100; i++) {
            sb.append("a");
        }
        String longUserId = sb.toString();
        
        // 执行测试
        Map<String, Object> result = controller.sendMessage(longUserId, "Hello");

        // 验证结果结构
        assertNotNull(result);
        assertTrue(result.containsKey("code"));
        assertTrue(result.containsKey("message"));
        
        // 验证返回码是200或500（取决于用户是否在线）
        Integer code = (Integer) result.get("code");
        assertTrue(code == 200 || code == 500, "返回码应该是200或500");
    }

    @Test
    void testControllerInstantiation() {
        // 测试控制器可以正常实例化
        WebSocketTestController newController = new WebSocketTestController();
        assertNotNull(newController);
    }

    @Test
    void testResponseFormatConsistency() {
        // 测试所有接口的响应格式一致性
        Map<String, Object>[] results = new Map[]{
            controller.getOnlineCount(),
            controller.getOnlineUsers(),
            controller.getWebSocketInfo(),
            controller.sendMessage("testuser", "testmessage")
        };

        for (Map<String, Object> result : results) {
            assertNotNull(result, "响应不应为null");
            assertTrue(result.containsKey("code"), "响应应包含code字段");
            assertTrue(result.containsKey("message"), "响应应包含message字段");
            
            Object code = result.get("code");
            assertTrue(code instanceof Integer, "code应该是Integer类型");
            
            Object message = result.get("message");
            assertTrue(message instanceof String, "message应该是String类型");
        }
    }

    @Test
    void testErrorHandling() {
        // 测试错误处理
        Map<String, Object> result1 = controller.sendMessage(null, "message");
        Map<String, Object> result2 = controller.sendMessage("user", null);
        Map<String, Object> result3 = controller.sendMessage("", "message");

        // 验证所有错误情况都返回500状态码
        assertEquals(500, result1.get("code"));
        assertEquals(500, result2.get("code"));
        assertEquals(500, result3.get("code"));

        // 验证错误消息
        assertTrue(((String) result1.get("message")).contains("失败"));
        assertTrue(((String) result2.get("message")).contains("失败"));
        assertTrue(((String) result3.get("message")).contains("失败"));
    }
}